package com.gopay.cashier.web.interceptor;

import java.util.Enumeration;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.gopay.cashier.common.exception.WebException;
import com.gopay.cashier.web.utils.CashierConfig;
import com.gopay.common.constants.proccode.ProcCodeConstants;

/**
 * 检查sql注入的拦截器
 * 
 * @InjectionInterceptor.java
 * @author zhanglei
 * @2013-3-22 下午2:27:30 www.gopay.com.cn Inc.All rights reserved.
 */
public class InjectionInterceptor extends HandlerInterceptorAdapter {
    protected final static Log logger = LogFactory.getLog(InjectionInterceptor.class);

    private static final String checkChar = "[\r\n|&;$%'\'\"<>()+,\\\\]";
    {
        logger.warn("INJECTION_INTERCEPTOR_DISABLED = "
                + CashierConfig.getBool(CashierConfig.INJECTION_INTERCEPTOR_DISABLED));
    }
    /**
     * 进行不安全脚本校验的页面
     */
    private String checkUrls;

    /**
     * 不进行校验的参数
     */
    private Set<String> escapeParamNames;

    @Override
    @SuppressWarnings("unchecked")
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (CashierConfig.getBool(CashierConfig.INJECTION_INTERCEPTOR_DISABLED)) return true;

        String url = request.getRequestURI();
        request.setCharacterEncoding("UTF-8");
        if (urlIsInjection(url)) {
            /* 遍历request中的参数，若存在不安全脚本，跳转到公共错误页 */
            for (Enumeration<String> enumeration = request.getParameterNames(); enumeration.hasMoreElements();) {
                String name = (String) enumeration.nextElement();
                /* 判断是否为不需进行校验的参数 */
                if (escapeParamNames.contains(name)) continue;

                String value = request.getParameter(name);
                value.replaceAll(checkChar, "");
                if (!value.equals(value.replaceAll(checkChar, ""))) {
                    logger.error(String.format("[url:%s, key:%s, value:%s]提交参数有误！check-injection!", url, name, value));
                    throw new WebException(ProcCodeConstants.PROC_CODE_100F2001);
                }
            }
        }
        return true;
    }

    private boolean urlIsInjection(String url) {
        if (StringUtils.isBlank(checkUrls)) return false;
        String[] allowUrls = StringUtils.split(checkUrls, ",");
        for (int i = 0; i < allowUrls.length; i++) {
            if (url.indexOf(allowUrls[i]) != -1) return true;
        }
        return false;
    }

    public String getCheckUrls() {
        return checkUrls;
    }

    public void setCheckUrls(String checkUrls) {
        this.checkUrls = checkUrls;
    }

    public Set<String> getEscapeParamNames() {
        return escapeParamNames;
    }

    public void setEscapeParamNames(Set<String> escapeParamNames) {
        this.escapeParamNames = escapeParamNames;
    }

}
